﻿using System;
using System.Net;
using System.Collections.Generic;
using System.ComponentModel;
using System.ServiceModel;
namespace DotNetAgent.Core
{
	public class TcpConnector : IDisposable
	{
		// Identity
		private string _i_Name = null;
		public string i_Name
		{
			get { return _i_Name; }
		}

		private string _i_Type = null;
		public string i_Type
		{
			get { return _i_Type; }
		}

		private Agent _i_Owner = null;
		protected Agent i_Owner
		{
			get { return _i_Owner; }
		}

		private string _i_LogName = null;
		public string i_LogName
		{
			get { return _i_LogName; }
		}

		// Outer Communication
		protected ServiceHost i_ServiceHost = null;

		String i_Address = "";
		public String Address
		{
			get { return i_Address; }
			set { i_Address = value; }
		}

		// Directory Facilitator
		//private Dictionary<String, String> i_DF;
		//public Dictionary<String, String> DF
		//{
		//    get
		//    {
		//        return i_DF;
		//    }
		//}

		public TcpConnector(Agent p_Owner, Dictionary<String, Object> p_Args)
		{
			try
			{
				// Identity
				if (!p_Args.ContainsKey("Name"))
				{
					throw new AgentException("Activation", "Name not specified");
				}
				_i_Name = p_Args["Name"] as String;
				_i_Type = this.GetType().AssemblyQualifiedName;
				_i_Owner = p_Owner;
				
				if (i_Owner == null)
				{
					throw new AgentException("Activation", "Owner not specified");
				}

				_i_LogName = i_Owner.i_LogName + "." + i_Name;

				// Communication
				if (p_Args.ContainsKey("Port"))
				{
					Address = "net.tcp://localhost:" + p_Args["Port"];
					i_ServiceHost = new ServiceHost(typeof(AgentService));
					i_ServiceHost.AddServiceEndpoint(typeof(IAgentService), new NetTcpBinding(), Address);
					if (i_ServiceHost != null)
					{
						i_ServiceHost.Open();
					}
					LogInfo("Activation", "Opened Communications");
				}
				else
				{
					throw new AgentException("Activation", "No port specified");
				}
			}
			catch (Exception ex)
			{
				throw new AgentException("Activation", "Error While Activating", ex);
			}
		}

		public void Dispose()
		{
			Exception Ex;
			try
			{
				if (i_ServiceHost != null)
				{
					i_ServiceHost.Close();
				}
				LogInfo("Deactivation", "Closed Communications");
			}
			catch (Exception exception2)
			{
				Ex = exception2;
				throw new AgentException("Deactivation", "Error While Deactivating", Ex);
			}
		}

		//public String GetAgentAddress(String p_AgentName)
		//{
		//    try
		//    {
		//        if (DF.ContainsKey(p_AgentName))
		//        {
		//            return DF[p_AgentName];
		//        }
		//        throw new AgentException("GetAgentAddress", "Unknown Agent " + p_AgentName);
		//    }
		//    catch (Exception Ex)
		//    {
		//        throw new AgentException("GetAgentAddress", "Error while retrieving Agent Address", Ex);
		//    }
		//}

		public bool Send(String p_SenderName, String p_RecipientName, String p_MsgType, Object p_MsgBody)
		{
			Agent A = i_Owner.GetAgent(p_RecipientName);

			if (A == null)
			{
				return false;
			}
			A.Recv(new AgentMessage(p_SenderName, p_RecipientName, p_MsgType, p_MsgBody));
			return true;
		}

		//public AgentMessage Send(AgentMessage p_Msg, int p_Timeout = -1)
		//{
		//    IAgentService s = new ChannelFactory<IAgentService>(new NetTcpBinding(), p_Msg.ToAddress).CreateChannel();
		//    AgentMessage l_Reply = s.Recv(p_Msg);
		//    (s as ICommunicationObject).Close();
		//    return l_Reply;
		//}

		protected void LogError(string Source, string Msg, Exception Ex)
		{
			i_Owner.LogError(i_LogName + "." + Source, Msg, Ex);
		}
		protected void LogInfo(string Source, string Msg)
		{
			i_Owner.LogInfo(i_LogName + "." + Source, Msg);
		}
		protected void LogWarning(string Source, string Msg)
		{
			i_Owner.LogWarning(i_LogName + "." + Source, Msg);
		}
	}
}